package com.foreveross.proxyip.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import com.foreveross.proxyip.core.http.ipdoload.website.WebSiteDoload;
import com.foreveross.proxyip.core.pools.AvailablePool;

public class ThreadUtils {
	private static final Logger log =  Logger.getLogger(WebSiteDoload.class);
	
	/**
	 * 
	 * @param constructor 第一个参数是集合，每个子线程处理的集合，其余参数由args提供
	 * @param iplist 处理集合
	 * @param threadMaxCellCount 每个线程处理集合最大数量
	 * @param threadTimeout 线程处理时间超出时间
	 * @param Object...args constructor的参数
	 * @throws Exception
	 */
		@SuppressWarnings({ "rawtypes", "unchecked" })
		public static void openThreads(Constructor constructor, List list,
				int threadMaxCellCount,long threadTimeout,Object...args) throws  Exception {
			int threadCount = list.size()/threadMaxCellCount;
			
			if(threadCount != 0){
			threadCount = list.size()%threadMaxCellCount!=0?threadCount+1:threadCount;
			}else{
				threadCount = 1;
			}
			ExecutorService es = Executors.newFixedThreadPool(threadCount);
			try{
			List<Future> futureList = new ArrayList<Future>();
			
			for(int i=0;i<threadCount;i++){
				List tempIpList = null;
				if(i+1==threadCount){//最后一次
					tempIpList = new Vector(list.subList(i*threadMaxCellCount, list.size()));
				}else{
					tempIpList = new Vector(list.subList(i*threadMaxCellCount, i*threadMaxCellCount+threadMaxCellCount));
				}
				Object []params = new Object[args==null?1:args.length+1];
				params[0] = tempIpList;
				int k=1;
				if(args!=null){
					for(Object obj :args){
						params[k]=obj;
						k++;
					}
				}
				Callable runer= (Callable)constructor.newInstance(params);
				Future f = es.submit(runer);
				futureList.add(f);
			}
			
			//判断线程是否都执行完
			int j = 0;
			for(Future f: futureList){
				try{
				Object o= f.get(threadTimeout, TimeUnit.MILLISECONDS);//设置超时时间
				}catch(Exception e){
					if(args.length>0&&args[0] instanceof  AvailablePool){
						AvailablePool pool = (AvailablePool)args[0];
						log.error(pool.poolSign + " timeout " + constructor.getName());
					}
					log.error(e);
				}
				j++;
//				log.debug("线程完成："+j);
			}
			}catch(Exception e){
				throw e;
			}finally{
				es.shutdown();
			}
//			log.debug("执行完一次操作");
		}
}
